package com.uduemc.biso.node.web.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.uduemc.biso.core.extities.center.custom.statistics.*;
import com.uduemc.biso.core.utils.RestResult;
import com.uduemc.biso.node.core.feign.*;
import com.uduemc.biso.node.core.utils.RestResultUtil;
import com.uduemc.biso.node.web.api.service.HostService;
import com.uduemc.biso.node.web.api.service.SiteService;
import com.uduemc.biso.node.web.api.service.StatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Service
public class StatisticsServiceImpl implements StatisticsService {

	@Autowired
	private HRobotsFeign hRobotsFeign;
	@Autowired
	private HDomainFeign hDomainFeign;

	@Autowired
	private SConfigFeign sConfigFeign;

	@Autowired
	private HConfigFeign hConfigFeign;

	@Autowired
	private SComponentFeign sComponentFeign;

	@Autowired
	private HostService hostServiceImpl;

	@Autowired
	private SiteService siteServiceImpl;

	@Autowired
	private SSystemFeign sSystemFeign;

	@Autowired
	private HSSLFeign hsslFeign;

	@Autowired
	private SSystemItemCustomLinkFeign sSystemItemCustomLinkFeign;

	@Override
	public NodeTemplateRankTrial queryTemplateRankTrial(int trial, int review, int templateAll, int orderBy, int count) throws IOException {
		NodeTemplateRankTrial nodeTemplateRankTrial = new NodeTemplateRankTrial();
		switch (trial) {
		case -1:
			nodeTemplateRankTrial.setAll(queryTemplateRank(-1, review, templateAll, orderBy, count));
			NodeTemplateRank all = nodeTemplateRankTrial.getAll();
			if (all != null && CollUtil.isNotEmpty(all.getRows())) {
				List<NodeTemplateRankRows> rows = all.getRows();
				String templateIdsString = CollUtil.join(rows, ",", item -> {
					return String.valueOf(item.getTemplateId());
				});
				RestResult restResult = sConfigFeign.queryTemplateByTrialReviewTemplateIds(1, review, templateIdsString);
				NodeTemplateRank formalNodeTemplateRank = RestResultUtil.data(restResult, NodeTemplateRank.class);
				restResult = sConfigFeign.queryTemplateByTrialReviewTemplateIds(0, review, templateIdsString);
				NodeTemplateRank trialNodeTemplateRank = RestResultUtil.data(restResult, NodeTemplateRank.class);
				if (formalNodeTemplateRank == null || trialNodeTemplateRank == null) {
					return null;
				}
				if (rows.size() != formalNodeTemplateRank.getRows().size() || rows.size() != trialNodeTemplateRank.getRows().size()) {
					return null;
				}

				return new NodeTemplateRankTrial(all, formalNodeTemplateRank, trialNodeTemplateRank);

			}
			break;
		case 0:
			nodeTemplateRankTrial.setTrial(queryTemplateRank(0, review, templateAll, orderBy, count));
			break;
		case 1:
			nodeTemplateRankTrial.setFormal(queryTemplateRank(1, review, templateAll, orderBy, count));
			break;
		default:
			break;
		}
		return nodeTemplateRankTrial;
	}

	@Override
	public NodeTemplateRank queryTemplateRank(int trial, int review, int templateAll, int orderBy, int count) throws IOException {
		RestResult restResult = sConfigFeign.queryTemplateRank(trial, review, templateAll, orderBy, count);
		return RestResultUtil.data(restResult, NodeTemplateRank.class);
	}

	@Override
	public NodeTemplate queryTemplate(int trial, int review, long templateId) throws IOException {
		RestResult restResult = sConfigFeign.queryTemplate(trial, review, templateId);
		return RestResultUtil.data(restResult, NodeTemplate.class);
	}

	@Override
	public NodeFunctionRankTrial functionRank(int review, List<FunctionStatisticsTypeEnum> listFunctionStatisticsTypeEnum) throws IOException {
		NodeFunctionRank all = functionRank(-1, review, listFunctionStatisticsTypeEnum);
		NodeFunctionRank trial = functionRank(0, review, listFunctionStatisticsTypeEnum);
		NodeFunctionRank formal = functionRank(1, review, listFunctionStatisticsTypeEnum);
		return new NodeFunctionRankTrial(all, formal, trial);
	}

	@Override
	public NodeFunctionRank functionRank(int trial, int review, List<FunctionStatisticsTypeEnum> listFunctionStatisticsTypeEnum) throws IOException {
		Integer hostTotal = hostServiceImpl.queryAllCount(trial, review);
		Integer siteTotal = siteServiceImpl.queryAllCount(trial, review);

		List<NodeFunctionRankRows> rowsList = new ArrayList<>();
		if (CollUtil.isNotEmpty(listFunctionStatisticsTypeEnum)) {
			NodeFunctionRankRows nodeFunctionRankRows = null;
			for (FunctionStatisticsTypeEnum typeEnum : listFunctionStatisticsTypeEnum) {
				String method = StrUtil.lowerFirst(typeEnum.name());
				Class<? extends StatisticsService> classStatisticsService = this.getClass();
				Method methodStatisticsService = null;
				try {
					methodStatisticsService = classStatisticsService.getMethod(StrUtil.lowerFirst(method), int.class, int.class);
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				}
				if (methodStatisticsService != null) {
					try {
						nodeFunctionRankRows = (NodeFunctionRankRows) methodStatisticsService.invoke(this, trial, review);
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}
					rowsList.add(nodeFunctionRankRows);
				}
			}
			rowsList.sort(Comparator.comparingInt(NodeFunctionRankRows::getCount).reversed());
		}
		return NodeFunctionRank.makeNodeTemplateRank(hostTotal, siteTotal, rowsList);
	}

	@Override
	public NodeFunctionRankRows footMenu(int trial, int review) throws IOException {
		RestResult restResult = sConfigFeign.queryFootMenuCount(trial, review);
		Integer data = RestResultUtil.data(restResult, Integer.class);
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName, data);
	}

	@Override
	public NodeFunctionRankRows emailRemind(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = hConfigFeign.queryEmailRemindCount(trial, review);
		Integer data = RestResultUtil.data(restResult, Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName, data);
	}

	@Override
	public NodeFunctionRankRows keywordFilter(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = hConfigFeign.queryKeywordFilterCount(trial, review);
		Integer data = RestResultUtil.data(restResult, Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName, data);
	}

	@Override
	public NodeFunctionRankRows localVideo(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = sComponentFeign.queryLocalVideoCount(trial, review);
		Integer data = RestResultUtil.data(restResult, Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName, data);
	}

	@Override
	public NodeFunctionRankRows localSearch(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = sComponentFeign.queryLocalSearchCount(trial, review);
		Integer data = RestResultUtil.data(restResult, Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName, data);
	}

	@Override
	public NodeFunctionRankRows articleSystem(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = sSystemFeign.queryArticleCount(trial, review);
		Integer data = RestResultUtil.data(restResult,Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName,data);
	}

	@Override
	public NodeFunctionRankRows produceSystem(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = sSystemFeign.queryProduceCount(trial, review);
		Integer data = RestResultUtil.data(restResult,Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName,data);
	}

	@Override
	public NodeFunctionRankRows bindSSL(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = hsslFeign.queryBindSSLCount(trial,review);
		Integer data = RestResultUtil.data(restResult,Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName,data);
	}

	@Override
	public NodeFunctionRankRows systemItemCustomLink(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = sSystemItemCustomLinkFeign.querySystemItemCustomLinkCount(trial, review);
		Integer data = RestResultUtil.data(restResult,Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName,data);
	}

	@Override
	public NodeFunctionRankRows domainRedirect(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = hDomainFeign.queryDomainRedirectCount(trial, review);
		Integer data = RestResultUtil.data(restResult,Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName,data);
	}

	@Override
	public NodeFunctionRankRows websiteRobots(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = hRobotsFeign.queryWebsiteRobotsCount(trial,review);
		Integer data = RestResultUtil.data(restResult,Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName,data);
	}

	@Override
	public NodeFunctionRankRows websiteMap(int trial, int review) throws IOException {
		String methodName = StrUtil.upperFirst(Thread.currentThread().getStackTrace()[1].getMethodName());
		RestResult restResult = hConfigFeign.queryWebsiteMapCount(trial, review);
		Integer data = RestResultUtil.data(restResult, Integer.class);
		return NodeFunctionRankRows.makeNodeFunctionRankRows(methodName,data);
	}


}
